﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Xml;
using Jayden.Dll.Sc2.Descriptions;
using Jayden.Dll.Sc2.Descriptions.Protoss;
using Jayden.Dll.Sc2.Descriptions.Terran;
using Jayden.Dll.Sc2.Descriptions.Zerg;

namespace Jayden.Sc2
{
	public class RaceDictionary
	{
		private Dictionary<string, RaceDescription> m_Races;

		private RaceDescription m_Terran;
		private RaceDescription m_Protoss;
		private RaceDescription m_Zerg;

		private string m_Version;

		public RaceDictionary()
		{
			using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Jayden.Dll.Sc2.Descriptions.xml"))
			{
				XmlDocument document = new XmlDocument();
				document.Load(stream);
				Load(document);
			}
		}

		public RaceDictionary(string filename)
		{
			XmlDocument document = new XmlDocument();
			document.Load(filename);
			Load(document);
		}

		private void Load(XmlDocument doc)
		{
			m_Version = doc.DocumentElement.Attributes["version"].Value;
			m_Races = new Dictionary<string, RaceDescription>(StringComparer.InvariantCultureIgnoreCase);
			foreach(XmlNode node in doc.DocumentElement.ChildNodes)
				if (node is XmlElement && node.Name == "Race")
				{
					RaceDescription race = null;
					switch (node.Attributes["id"].Value)
					{
						case "Terran":
							race = new TerranRaceDescription(this, node);
							break;
						case "Protoss":
							race = new ProtossRaceDescription(this, node);
							break;
						case "Zerg":
							race = new ZergRaceDescription(this, node);
							break;
						default:
							race = new RaceDescription(this, node);
							break;
					}
					
					m_Races.Add(race.Id, race);
				}
		}

		public RaceDescription Terran
		{
			get
			{
				if (m_Terran == null)
					m_Terran = m_Races["Terran"];
				return m_Terran;
			}
		}
		public RaceDescription Protoss
		{
			get
			{
				if (m_Protoss == null)
					m_Protoss = m_Races["Protoss"];
				return m_Protoss;
			}
		}
		public RaceDescription Zerg
		{
			get
			{
				if (m_Zerg == null)
					m_Zerg = m_Races["Zerg"];
				return m_Zerg;
			}
		}

		public string Version { get { return m_Version; } }

		public IEnumerable<string> RaceIds { get { return m_Races.Keys; } }
		public IEnumerable<RaceDescription> Races { get { return m_Races.Values; } }
		public RaceDescription this[string raceId]
		{
			get
			{
				RaceDescription race = null;
				if (m_Races.TryGetValue(raceId, out race))
					return race;
				return null;
			}
		}

		public EntityDescription GetEntity(string id)
		{
			foreach (KeyValuePair<string, RaceDescription> pair in m_Races)
			{
				EntityDescription descr = pair.Value.GetEntity(id);
				if (descr != null)
					return descr;
			}
			return null;
		}

		public ActionDescription GetAction(string id)
		{
			foreach (KeyValuePair<string, RaceDescription> pair in m_Races)
			{
				ActionDescription descr = pair.Value.GetAction(id);
				if (descr != null)
					return descr;
			}
			return null;
		}
	}
}
